phing是(Phing is Not GNU make)的簡寫...(那make怎麼沒放進去XD),這是一個模仿apache ant的專案建置工具。只要寫好專案建置腳本(build.xml),就可以透過命令列的方式來建構專案。
不過...php是腳本語言,並不需要使用編譯器,那phing還能做什麼?其實一個完整的專案過程,還有很多的工作,這些都可以整合到腳本中,讓這些過程都可以透過命令列驅動並執行。同時每個建置階段,都可以設定相依性。這樣只要指示phing要執行哪一個步驟,phing也會把這個步驟前需要執行的工作也都一併完成。
參考:
http://www.phing.info/
之前試用過幾個工具,可以用來做單元測試、整合測試、檢測程式碼品質等等,其實這些工作都可以放進專案流程。另外在開發中,通常還會需要做幾項工作:
另外,即使不使用額外的伺服器,只要能透過cron定時檢測版本庫,然後驅動建構、測試的流程,而且測試結果都可以轉成html格式透過網頁伺服器來檢視的話,這其實就是一種持續整合了。
好了,不提那麼多,先來安裝phing。
phing也支援用composer的方式來安裝,同樣改一下composer.json:
{
"require":{
},
"require-dev": {
"phpunit/phpunit":"~3.7.5",
"phpunit/php-invoker":"~1.1.0",
"phpunit/phpunit-selenium":"~1.3.2",
"pdepend/pdepend":"~1.1",
"phpmd/phpmd":"~1.5",
"phing/phing":"~2.6.1"
}
}
然後執行composer update。執行完以後,把phing link到專案目錄,這樣執行會比較方便
> ln -s vendor/phing/phing/bin/phing
然後執行一下./phing看看:
Feng-Hsu-Pingteki-MacBook-Air:2-3a fillano$ ./phing
Buildfile: build.xml does not exist!
嗯,所以在執行前,需要寫一個建構的腳本,預設的名字是build.xml(這跟ant一樣)...那就先來看看怎麼寫這個腳本。
跟ant一樣,build.xml的組織結構是:
先來寫一個hello world好了:
<?xml version="1.0" encoding="UTF-8"?>
<project name="2-3a" default="main">
<target name="main">
<echo msg="Hello Phing." />
</target>
</project>
執行一下看看:
Feng-Hsu-Pingteki-MacBook-Air:2-3a fillano$ ./phing
Buildfile: /Users/fillano/builds/ironman6/2-3a/build.xml
2-3a > main:
[echo] Hello Phing.
BUILD FINISHED
Total time: 0.2400 seconds
其中:
在target加上depends屬性,就可以指定依賴關係,例如我想要加一個target叫做prepare,會在執行main之前執行:
<?xml version="1.0" encoding="UTF-8"?>
<project name="2-3a" default="main">
<target name="main" depends="prepare">
<echo msg="Hello Phing." />
</target>
<target name="prepare">
<echo msg="I'm prepared for main." />
</target>
</project>
執行結果:
Feng-Hsu-Pingteki-MacBook-Air:2-3a fillano$ ./phing
Buildfile: /Users/fillano/builds/ironman6/2-3a/build.xml
2-3a > prepare:
[echo] I'm prepared for main.
2-3a > main:
[echo] Hello Phing.
BUILD FINISHED
Total time: 0.2418 seconds
再來用比較真實的專案流程做例子。假設專案流程是這樣:
來把幾個東西組合一下:
<?xml version="1.0" encoding="UTF-8"?>
<project name="2-3a" default="dist">
<target name="dist" depends="build">
<zip destfile="dist/2-3a.zip">
<fileset dir="builds">
<include name="**/*.php" />
</fileset>
</zip>
</target>
<target name="build" depends="test">
<copy todir="builds">
<fileset dir="src">
<include name="**.php" />
</fileset>
</copy>
</target>
<target name="test" depends="clear">
<phpunit>
<formatter todir="reports" type="xml" outfile="phpunit_report.xml" />
<batchtest>
<fileset dir="tests">
<include name="TestScormTimeUtils.php" />
</fileset>
</batchtest>
</phpunit>
</target>
<target name="clear">
<delete>
<fileset dir="builds">
<include name="**.*" />
</fileset>
</delete>
<delete>
<fileset dir="reports">
<include name="**.*" />
</fileset>
</delete>
<delete>
<fileset dir="dist">
<include name="**.*" />
</fileset>
</delete>
</target>
</project>
預設的目標是dist,他會把builds目錄中的php檔壓縮成2-3a.zip,放在dist目錄。在執行dist前,會先執行build,他會把src目錄中的php檔複製到builds目錄。在執行build之前,會先執行test。test會執行phpunit,使用tests/TestScormTimeUtils.php作為測試目標,然後把測試報告以xml格式存放在reports/phpunit_report.xml。在執行test之前,會先執行clear,把reports、builds、dist目錄清空。
執行結果:
Feng-Hsu-Pingteki-MacBook-Air:2-3a fillano$ ./phing
Buildfile: /Users/fillano/builds/ironman6/2-3a/build.xml
2-3a > clear:
[delete] Deleting 1 files from builds
[delete] Deleting 1 files from reports
[delete] Deleting 1 files from dist
2-3a > test:
2-3a > build:
[copy] Copying 1 file to /Users/fillano/builds/ironman6/2-3a/builds
2-3a > dist:
[zip] Building zip: /Users/fillano/builds/ironman6/2-3a/dist/2-3a.zip
BUILD FINISHED
Total time: 0.3412 seconds
只要下一個命令,就可以完成複雜建構過程,使用phing真的可以節省很多時間。
執行完畢後,專案目錄檔案就會有這些:
Feng-Hsu-Pingteki-MacBook-Air:2-3a fillano$ tree src tests builds reports dist
src
└── ScormTimeUtils.php
tests
├── TestScormTimeUtils.php
└── TestSelenium.php
builds
└── ScormTimeUtils.php
reports
└── phpunit_report.xml
dist
└── 2-3a.zip
其中builds、reports、dist目錄中的檔案,都是建構過程中產生的。
phing網站上的文件相當完整,而且內建許多的task,也可以自定task, type等。使用時,可以根據建置的需求選擇需要的task,如果不夠用,也可以考慮自己寫。不過他抄ant真的很徹底